/*jslint sloppy: true */
/*global require, module */
var forEach = require('./util').forEach,
	extend = require('./util').extend,
	parseLog = require('./parseLog'),
    isNumber = require('./util').isNumber,
	copyArray = require('./util').copyArray,
	isArray = require('./util').isArray;

function fixOffset(dataArray, clock) {
	var data = [];
	clock = isNumber(clock) ? clock : 10;
	forEach(dataArray, function (delay) {
		var d = parseInt(delay / clock, 0) * 10;
		if (isNumber(delay)) {
			data.push(d < 0 ? 0 : d);
		} else {
			data.push(delay);
		}
	});
	return data;
}

function CaseResult(caseOpts, taskResult) {
	var log = caseOpts.log,
		sL = parseLog(log); // (S)tructed (L)og

	this.$$taskResult = taskResult;

	this.$executionLog = sL.resolvedLog;
	this.$linesOfLog = sL.availLines;
	this.$loopOption = sL.loopOption;
	this.$performanceData = sL.performance;

	this.$overview = {
		testingStartTime: log.baseTime,
		testingMachineTime: log.logs[log.logs.length - 1][1],
		times: sL.passedNumber + sL.failureNumber,
		passedFrequency: sL.passedNumber,
		failureFrequency: sL.failureNumber
	};
	this.$overview.isAllPassed = !this.$overview.failureFrequency;
}
CaseResult.prototype.$queryLogByLoopOption = function (loopOpt) {
	var logByLoopFilter = [];

	if (!loopOpt) {
		return this.$executionLog;
	}

	forEach(loopOpt, function (loopNumber) {
		logByLoopFilter.push(this.$executionLog[loopNumber]);
	}, this);

	return logByLoopFilter;
};
CaseResult.prototype.getAvailableLineNumbers = function () {
	return copyArray(this.$linesOfLog);
};
CaseResult.prototype.isLineContained = function (line) {
	return this.$linesOfLog.indexOf(line) !== -1;
};
CaseResult.prototype.getOverview = function () {
	return this.$overview;
};
CaseResult.prototype.getLog = function (lineArray, loopMode) {
	// optional loopMode: All:'A'(default), SuccessOnly:'P',
	// ErrorOnly:'F', array[<loopNumber|number>]
	var lineOptions = {},
		outputLog = [],
		logByLoop = [];

	forEach(lineArray, function (lineNumber) {
		lineOptions[lineNumber] = true;
	});

	if (loopMode === 'F' || loopMode === 'P') {
		logByLoop = this.$queryLogByLoopOption(this.$loopOption[map[loopMode]]);
	} else if (isArray(loopMode)) {
		logByLoop = this.$queryLogByLoopOption(loopMode);
	} else {
		logByLoop = this.$queryLogByLoopOption();
	}

	forEach(logByLoop, function (loopLog) {
		forEach(loopLog, function (insLog) {
			var l = insLog.line;
			if (l === 0 || lineOptions.hasOwnProperty(l)) {
				outputLog.push(insLog);
			}
		});
	});

	return outputLog;
};
CaseResult.prototype.getAssertIdList = function () {
	var list = [];

	forEach(this.$performanceData, function (d, key) {
		list.push(key);
	});

	return list;
};
CaseResult.prototype.getPerformanceByAssertId = function (idArray, isOffsetFixed) {
	var data = {},
		pL = this.$performanceData;

	idArray = idArray || this.getAssertIdList();

	forEach(idArray, function (assertKey) {
		var d = pL[assertKey].data;

		if (pL.hasOwnProperty(assertKey)) {
			data[assertKey] = isOffsetFixed ? fixOffset(d) : d;
		} else {
			throw new Error('AssertKey: ' + assertKey + ' is not exited.');
		}
	});
	return data;
};
CaseResult.prototype.getPerformanceOverview = function () {
	// {avg:..., variance:..., max:..., min:... }
	var pOList = [];// (P)erformance (O)verview
	forEach(this.$performanceData, function (pO, assertId) {
		pOList.push(extend({}, pO, {
			assertId: assertId,
			caseName: this.$overview.name,
			cR: this
		}));
	}, this);

	return pOList;
};

module.exports = CaseResult;
